package com.northpool.operator.common.database;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import com.northpool.operator.bean.DatasetBean;
import com.northpool.operator.common.database.bean.ConfigBean;
import com.northpool.operator.common.database.bean.DataSourceBean;
import com.northpool.operator.common.database.bean.DataSourceType;
import com.northpool.operator.common.database.bean.NacosProperties;
import com.northpool.operator.common.sm.SM4;
import org.yaml.snakeyaml.Yaml;

import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class DatabaseUtils {
    final static String DATASOURCE_CONFIG_FILE = "dms_database_connection.yml";
    private static Map<String, DataSourceBean> dataSourceMap = new LinkedHashMap<>();
    private static boolean isInit = false;


    public static void init(NacosProperties properties) {
        System.setProperty("nacos.logging.default.config.enabled", "false");
        if (isInit) {
            return;
        }
        // 优先从meta-api中读取,其次才是Nacos
        try {
            // 创建ConfigService实例
            ConfigService configService = NacosFactory.createConfigService(properties.getProperties());

            // 获取配置
            TimeInterval timer = DateUtil.timer();
            String config = configService.getConfig(DATASOURCE_CONFIG_FILE, properties.getGroup(), 30000);
            Console.log("获取配置耗时：{}", timer.interval());
            if (StrUtil.isNullOrUndefined(config)) {
                throw new RuntimeException("未找到数据源配置信息," + DATASOURCE_CONFIG_FILE + "获取异常");
            }
            Yaml yaml = new Yaml();
            Map<String, Object> configMap = yaml.load(config);
            Map<String, Object> datasource = (Map<String, Object>) configMap.get("datasource");
            List<Map<String, String>> datasourceList = (List<Map<String, String>>) datasource.get("array");

            // 设置并发度
            datasourceList.forEach(dbMap -> {
                try {
                    String type = dbMap.get("type");
                    List<DataSourceType> collect = Arrays.stream(DataSourceType.values()).filter(t -> t.name().equals(type)).collect(Collectors.toList());
                    if (collect.isEmpty()) {
                        return; // 跳过不支持的数据源
                    }

                    DataSourceBean dataSourceBean = new DataSourceBean();
                    dataSourceBean.setPassword(dbMap.get("password"));
                    dataSourceBean.setDataCenterId(dbMap.get("dataCenterId"));
                    dataSourceBean.setName(dbMap.get("name"));
                    dataSourceBean.setType(DataSourceType.valueOf(dbMap.get("type")));
                    dataSourceBean.setUser(dbMap.get("user"));
                    ConfigBean configBean = JSONObject.parseObject(dbMap.get("config"), ConfigBean.class);
                    dataSourceBean.setConfig(configBean);
                    dataSourceBean.setUrl(dbMap.get("url"));
                    dataSourceBean.setTypeCode(dbMap.get("typeCode"));
                    dataSourceMap.put(dataSourceBean.getDataCenterId(), dataSourceBean);
                } catch (Exception ex) {
                    Console.error(ex.getMessage(), ex);
                }
            });
            isInit = true;
        } catch (NacosException e) {
            throw new RuntimeException("nacos 获取数据源信息异常: " + e.getMessage());
        }
    }

    public static void init() {
        NacosProperties properties = NacosConfigReader.getNacosProperties();
        TimeInterval timer = DateUtil.timer();
        init(properties);
        System.out.println("初始化数据源耗时：" + timer.intervalSecond() + "秒");
    }

    public static String getDataSourceName(String dataSourceId) {
        if (!isInit) {
            init();
        }
        DataSourceBean dataSourceBean = dataSourceMap.get(dataSourceId);
        if (dataSourceBean == null) {
            return null;
        }
        return dataSourceBean.getName();
    }

    public static String getDataSourceJson(String dataSourceId) {
        if (!isInit) {
            init();
        }
        DataSourceBean dataSourceBean = dataSourceMap.get(dataSourceId);
        if (dataSourceBean == null) {
            throw new RuntimeException("数据源未找到：" + dataSourceId);
        }
        if (DataSourceType.postgreSQL.equals(dataSourceBean.getType())) {
//            dataSourceBean.setUrl("jdbc:postgresql://192.168.164.45:5432/tool_data");
            return StrUtil.format(
                    "{\"id\":\"{}\",\"url\":\"{}\",\"password\":\"{}\",\"user\":\"{}\",\"dataSourceType\":\"postgreSQL\"}",
                    dataSourceBean.getDataCenterId(),
                    dataSourceBean.getUrl().replace("jdbc:postgresql://", ""),
                    SM4.decryptData_ECB(dataSourceBean.getPassword()),
                    dataSourceBean.getUser()
            );
        } else if (DataSourceType.mongoDb.equals(dataSourceBean.getType())) {
            //mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
            return StrUtil.format(
                    "{\"id\":\"{}\",\"uri\":\"mongodb://{}\",\"dataSourceType\":\"mongodb\"}",
                    dataSourceBean.getDataCenterId(),
                    dataSourceBean.getUrl()
            );
        } else if (DataSourceType.fgdb.equals(dataSourceBean.getType())) {
            return StrUtil.format(
                    "{\"id\":\"{}\",\"dataSourceType\":\"fgdb\",\"filePath\":\"{}\"}",
                    dataSourceBean.getDataCenterId(),
                    dataSourceBean.getUrl()
            );
        } else if (DataSourceType.highgo.equals(dataSourceBean.getType())) {
            return StrUtil.format(
                    "{\"id\":\"{}\",\"url\":\"{}\",\"password\":\"{}\",\"user\":\"{}\",\"dataSourceType\":\"highgo\"}",
                    dataSourceBean.getDataCenterId(),
                    dataSourceBean.getUrl().replace("jdbc:postgresql://", "").replace("jdbc:highgo://", ""),
                    SM4.decryptData_ECB(dataSourceBean.getPassword()),
                    dataSourceBean.getUser()
            );
        } else if (DataSourceType.kingbase.equals(dataSourceBean.getType())) {
            return StrUtil.format(
                    "{\"id\":\"{}\",\"url\":\"{}\",\"password\":\"{}\",\"user\":\"{}\",\"dataSourceType\":\"kingbase\"}",
                    dataSourceBean.getDataCenterId(),
                    dataSourceBean.getUrl().replace("jdbc:postgresql://", "").replace("jdbc:kingbase8://", ""),
                    SM4.decryptData_ECB(dataSourceBean.getPassword()),
                    dataSourceBean.getUser()
            );
        } else if (DataSourceType.oracle.equals(dataSourceBean.getType())) {
            return StrUtil.format(
                    "{\"id\":\"{}\",\"url\":\"{}\",\"password\":\"{}\",\"user\":\"{}\",\"dataSourceType\":\"oracle\"}",
                    dataSourceBean.getDataCenterId(),
                    dataSourceBean.getUrl().replace("jdbc:oracle://", ""),
                    SM4.decryptData_ECB(dataSourceBean.getPassword()),
                    dataSourceBean.getUser()
            );
        } else if (DataSourceType.mysql.equals(dataSourceBean.getType())) {
            return StrUtil.format(
                    "{\"id\":\"{}\",\"url\":\"{}\",\"password\":\"{}\",\"user\":\"{}\",\"dataSourceType\":\"mysql\"}",
                    dataSourceBean.getDataCenterId(),
                    dataSourceBean.getUrl().replace("jdbc:mysql://", ""),
                    SM4.decryptData_ECB(dataSourceBean.getPassword()),
                    dataSourceBean.getUser()
            );
        } else {
            throw new RuntimeException("暂不支持的数据源: " + dataSourceBean.getType());
        }
    }

    public static String buildDatasetJson(String dataSourceId, String tableName) {
        JSONObject dataset = new JSONObject();
        dataset.put("dataSourceId", dataSourceId);
        dataset.put("tableName", tableName);
        return dataset.toJSONString();
    }

    public static DatasetBean buildDataset(String datasetJson) {
        return JSONObject.parseObject(datasetJson, DatasetBean.class);
    }

    public static void main(String[] args) {
        DatabaseUtils.init();
        System.out.println(DatabaseUtils.getDataSourceJson("highgo"));
    }
}
   